﻿
Imports std
Imports runrroom

Public Class jobmgr_t
    Private m As map(Of String, progress) = Nothing
    Private l As vector(Of progress) = Nothing
    Private timer3Index As Guid = Guid.Empty
    Private locker As sequentialLock = Nothing

    Public Function addjob(ByVal cmd As vector(Of String), ByVal r As distrrule, _
                           Optional ByRef jobid As String = Nothing) As Boolean
        jobid = createGUID()
        Dim p As progress = Nothing
        p = New progress(jobid, cmd, r)
        lock()
        m(jobid) = p
        l.push_back(p)
        unlock()
        'call an updateStatus to make the job start now
        updateStatus()
        Return True
    End Function

    Private Function at(ByVal jobid As String, ByRef job As progress) As Boolean
        lock()
        Dim rtn As Boolean = False
        Dim it As map(Of String, progress).iterator = Nothing
        it = m.find(jobid)
        If it = m.end() Then
            rtn = False
        Else
            job = (+it).second
            rtn = True
        End If
        unlock()
        Return rtn
    End Function

    Public Function percent(ByVal jobid As String, ByRef p As percentage_t) As Boolean
        Dim job As progress = Nothing
        If at(jobid, job) Then
            p = job.percentage()
            Return True
        Else
            Return False
        End If
    End Function

    Private Sub lock()
        locker.wait()
    End Sub

    Private Sub unlock()
        locker.release()
    End Sub

    Private Sub updateStatus()
        lock()
        Dim i As Int64
        i = 0
        While i < l.size()
            l(i).step()
            If l(i).finish() Then
                If Now.Ticks() - l(i).finishticks() >= secondsToTicks(config.reserveJobInfoSeconds) Then
                    If Not jobuploader().insert(l(i)) Then
                        raiseError("cannot insert job info into jobuploader.", errorHandle.errorType.exclamation)
                    End If

                    m.erase(l(i).jobid())
                    l.erase(i)
                    i -= 1
                End If
            End If
            i += 1
        End While
        unlock()
    End Sub

    Public Sub New()
        m = New map(Of String, progress)()
        l = New vector(Of progress)()
        locker = New sequentialLock()
        timer3Index = timer3.addcall(AddressOf updateStatus, secondsToMilliseconds(60))
    End Sub

    Protected Overrides Sub Finalize()
        If timer3Index <> Guid.Empty Then
            assert(timer3.removecall(timer3Index))
            timer3Index = Guid.Empty
        End If
        MyBase.Finalize()
    End Sub
End Class
